home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / standards / misc / LPunch < prev    next >
Internet Message Format  |  1993-07-15  |  35KB

  1. From LISTSERV@TAUNIVM.TAU.AC.IL Mon Oct  7 14:19:00 1991
  2. Return-Path: <LISTSERV@TAUNIVM.TAU.AC.IL>
  3. Date:         Mon, 7 Oct 91 07:08:51 IST
  4. From: List Processor (1.2) <LISTSERV@TAUNIVM.TAU.AC.IL>
  5. Subject:      File: "LISTLPUN MEMO" being sent to you
  6. To: bzs@WORLD.STD.COM
  7.  
  8.                 LISTEARN List Processor, Release 1.0
  9.              -------------------------------------------
  10.           LISTEARN 1.0  (c) EARN Association 1989 is derived from:
  11.           LISTSERV 1.5o (c) Eric Thomas 1986,1987,1988,1989
  12.  
  13.  
  14.  
  15.       +-----------------------------------------------------------+
  16.       |   Revised LISTSERV: LISTSERV-Punch Implementation Guide   |
  17.       +-----------------------------------------------------------+
  18.       |                                                           |
  19.       |       Document number: R01-007-0 (October 4th, 1987)      |
  20.       |                                                           |
  21.       |         Author: Eric Thomas <ERIC@FRECP11.BITNET>         |
  22.       |                                                           |
  23.       |   Document fileid: "LISTLPUN MEMO"  (from "Info LPunch")  |
  24.       +-----------------------------------------------------------+
  25.  
  26.  
  27.  
  28.   Preface
  29.  
  30.  
  31.  
  32.   This  manual is a Reference Guide for application programmers who have
  33.   to implement the LISTSERV-Punch file transfer format  on  their  oper-
  34.   ating  system.    It  provides a complete technical description of the
  35.   LISTSERV-Punch format, along with a brief  summary  of  some  relevant
  36.   information about the CMS file system.  In addition, sample conversion
  37.   programs  in  PASCAL  and  C  are  provided  to assist the application
  38.   programmer in implementing a  satisfactory  LISTSERV-Punch  conversion
  39.   program on his system.
  40.  
  41.   NOTE: The  LISTSERV-Punch  file  transfer  format  was introduced with
  42.   release 1.4 of Revised LISTSERV.  Although the  LISTSERV-Punch  format
  43.   might  be expanded in the future to provide additional functions, full
  44.   upwards compatibility is warrantied  provided  that  the  user-written
  45.   conversion  program  strictly conforms to the standard defined in this
  46.   document.  Deviations from the norm (e.g. not ignoring  the  remainder
  47.   of the ID control card) might lead to problems with future releases of
  48.   LISTSERV.
  49.  
  50.  
  51.  
  52.   Conventions
  53.   -----------
  54.  
  55.   The  following  typographical conventions have been made in this docu-
  56.   ment to improve its readability:
  57.  
  58. | o   Recent changes in the publication are indicated by a vertical  bar
  59. |     in the left margin.
  60.  
  61. ! o   Intermediate  changes  between two releases of the document ("Pre-
  62. !     releases") are flagged with  an  exclamation  point  in  the  left
  63. !     margin.    Features described in this fashion should be considered
  64. !     as not documented and not officially supported until the  exclama-
  65. !     tion point is removed.
  66.  
  67. > o   Temporary   restrictions  or  circumventions  are  marked  with  a
  68. >     "greater than" sign in the left margin. This sign may also be used
  69. >     to signal obsolete features for which support will be  dropped  in
  70. >     the next release.
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.   LISTSERV-PUNCH FORMAT DESCRIPTION
  80.   _________________________________
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.   ****************
  88.   * Introduction *
  89.   ****************
  90.  
  91.  
  92.   The term "LISTSERV-Punch" refers to a "file transmission format" which
  93.   is  used  by LISTSERV when sending files larger than 80 characters per
  94.   record to computing systems which do not have the ability  to  process
  95.   Netdata, CARD DUMP or DISK DUMP format.  It was designed to accomodate
  96.   file  transmission  through mail-only gateways.   Its primary features
  97.   are:
  98.  
  99.   o   Ability to transfer files of any record length up to 65535 charac-
  100.       ters per record.  This limit is arbitrary and corresponds  to  the
  101.       longest string a high-level language compiler can usually handle.
  102.  
  103.   o   Ability  to transfer files without automatically padding or strip-
  104.       ping records of trailing blanks.   That is,  leading  or  trailing
  105.       blanks are not removed by the file transfer process itself.
  106.  
  107.   o   Simplicity of the decoding program.  Sample conversion programs in
  108.       PASCAL and C are provided at the end of this document.  The PASCAL
  109.       program was written and tested in about 45 minutes, and any PASCAL
  110.       programmer  should be able to adapt it very quickly to work on his
  111.       own system.
  112.       The C program should  work  unmodified  under  any  standard  UNIX
  113.       system,  but  might need to be improved to allow the specification
  114.       of input and output parameters  and/or  system-dependent  switches
  115.       for the various filing system calls.
  116.  
  117.   o   Acceptable  network efficiency: very little extra lines are gener-
  118.       ated, and trailing blanks are stripped before transmission.
  119.  
  120.   o   Possibility for a human reader  to  get  a  general  idea  of  the
  121.       contents  of  the  file  without  having to resort to a conversion
  122.       program.
  123.  
  124.  
  125.  
  126.  
  127.   ****************************
  128.   * Format of the INPUT file *
  129.   ****************************
  130.  
  131.  
  132.   A LISTSERV-Punch formatted file (also called  "card  deck",  with  the
  133.   term  "card"  being  used to refer to a 80-characters file record) has
  134.   the following outer aspect:
  135.  
  136.   +--------------------------------------------------------------------+
  137.   |    junk line                                                       |
  138.   |        .                                                           |
  139.   |        .                                                           |
  140.   |    junk line                                                       |
  141.   |                                                                    |
  142.   |   ID/ control card                                                 |
  143.   |                                                                    |
  144.   |    data line #1                                                    |
  145.   |        .                                                           |
  146.   |        .                                                           |
  147.   |    data line #n                                                    |
  148.   |                                                                    |
  149.   |   END/ control card                                                |
  150.   |                                                                    |
  151.   |    junk line                                                       |
  152.   |        .                                                           |
  153.   |        .                                                           |
  154.   |    junk line                                                       |
  155.   |                                                                    |
  156.   | Figure 1.  Input card deck format                                  |
  157.   +--------------------------------------------------------------------+
  158.  
  159.  
  160.  
  161.   Junk lines
  162.   ----------
  163.  
  164.  
  165.   Anything before  the  "ID/"  card  (e.g.  mail  header,  comments)  is
  166.   ignored.    Similarly,  anything  after  the  "END/" card (e.g. mailer
  167.   keywords, "Acknowledge-To:" field) is discarded.  Encountering the end
  168.   of the file without any ID or END card is an error.  However, encount-
  169.   ering an END card before any ID card is not an  error  since  anything
  170.   before the first ID card must be ignored without even being parsed.
  171.  
  172.  
  173.  
  174.   Control lines
  175.   -------------
  176.  
  177.  
  178.   The  ID card contains information about the file being sent, while the
  179.   END card is merely an end-of-stream indicator.   The format  of  these
  180.   two cards is:
  181.  
  182.   +--------------------------------------------------------------------+
  183.   |                 ID/filename filetype recfm lrecl reserved          |
  184.   |                 |  |        |        |     |    |                  |
  185.   |                 V  V        V        V     V    V                  |
  186.   | Column numbers: 1  4        13       22    24   29                 |
  187.   |                                                                    |
  188.   |                 END/reserved                                       |
  189.   |                 |   |                                              |
  190.   |                 V   V                                              |
  191.   | Column numbers: 1   5                                              |
  192.   |                                                                    |
  193.   | Blanks  shown  between  keywords are real.   See later on for more |
  194.   | information on the meaning of "filename", "recfm", etc.            |
  195.   |                                                                    |
  196.   | Figure 2.  Control cards format                                    |
  197.   +--------------------------------------------------------------------+
  198.  
  199.   NOTE: The end of the ID card (from column 30 onwards,  inclusive)  and
  200.   the  end  of  the  END  card  (from  column  5 onwards, inclusive) are
  201.   reserved fields which should be ignored  by  the  conversion  program.
  202.   Failure  to  observe  this  rule  might result in severe compatibility
  203.   problems with future releases of LISTSERV.
  204.  
  205.  
  206.  
  207.   Data lines
  208.   ----------
  209.  
  210.  
  211.  
  212.  
  213.   Folding algorithm
  214.  
  215.  
  216.   Each record of the source file is broken into  one  or  more  physical
  217.   "cards"  before  being transmitted.  The first card of each such group
  218.   will indicate the number of cards in the group, counting itself as one
  219.   card (i.e. this is not the number of continuation cards but the  total
  220.   number  of  cards),  and possibly the length of the source record line
  221.   (only if "recfm" is 'V' - see below).   The  remainder  of  the  first
  222.   card, as well as the second and following cards in the group, are pure
  223.   data  bytes.  The resulting concatenated record will have to be padded
  224.   with blanks as determined by the record length indication, if needed.
  225.  
  226.  
  227.  
  228.   Description of the format of a data line
  229.  
  230.  
  231.  
  232.   Fixed-length records
  233.  
  234.  
  235.  
  236.   +--------------------------------------------------------------------+
  237.   | recfm = F                                                          |
  238.   |                 ncards/data                                        |
  239.   |                 |      |                                           |
  240.   |                 V      V                                           |
  241.   | Column numbers: 1      2+Length(ncards)                            |
  242.   |                                                                    |
  243.   | Figure 3.  Data line format, fixed-length records                  |
  244.   +--------------------------------------------------------------------+
  245.  
  246.  
  247.  
  248.   Variable-length records
  249.  
  250.  
  251.  
  252.   +--------------------------------------------------------------------+
  253.   | recfm = V                                                          |
  254.   |                 lrecl/ncards/data                                  |
  255.   |                 |     |      |                                     |
  256.   |                 V     |      V                                     |
  257.   | Column numbers: 1     |      3+Length(lrecl)+Length(ncards)        |
  258.   |                       V                                            |
  259.   |                       2+Length(lrecl)                              |
  260.   |                                                                    |
  261.   | Figure 4.  Data line format, variable-length records               |
  262.   +--------------------------------------------------------------------+
  263.  
  264.   NCARDS    is the total number of cards in the group (ncards >= 1).
  265.  
  266.   LRECL     is the logical record length of the source file record asso-
  267.             ciated with the group; it does not appear in recfm  F  files
  268.             for which the record length is defined in the ID card.
  269.  
  270.  
  271.  
  272.  
  273.   ***************************************
  274.   * Summary of CMS file characteristics *
  275.   ***************************************
  276.  
  277.  
  278.   Since  LISTSERV  operates in an IBM VM/SP CMS environment and the file
  279.   will have to be received on a different operating system, a very short
  280.   description of the CMS file system has been included here.
  281.  
  282.  
  283.  
  284.   CMS file names
  285.   --------------
  286.  
  287.  
  288.   Under CMS, each file is identified by a "filename" and  a  "filetype",
  289.   both  of  them  being  strings  of  1 to 8 characters taken out of the
  290.   following set:
  291.  
  292.        A-Z   a-z   0-9   #$@-+:_
  293.  
  294.  
  295.   However, LISTSERV will never send a file containing a lowercase  char-
  296.   acter  in  its  filename or filetype, because a lot of systems have to
  297.   convert them to uppercase or will convert network interactive messages
  298.   to uppercase, thus making it impossible for users to enter mixed  case
  299.   file names in the commands they send to LISTSERV.
  300.  
  301.  
  302.  
  303.   CMS file structure
  304.   ------------------
  305.  
  306.  
  307.   CMS  files  consist  in  a  series of "records", as opposed to UNIX or
  308.   MS-DOS files which consist in a series of bytes.    When  calling  the
  309.   filing  system  to  perform a write operation, you must provide a full
  310.   record.  It is not possible to write "byte by byte" since this has  no
  311.   meaning  (you  could  of course write a series of one-byte records but
  312.   this would not create the file you  expected).    Each  CMS  file  has
  313.   therefore, among other attributes:
  314.  
  315.   o   A "number of records" field.
  316.  
  317.   o   A  "logical  record  length" (which is called lrecl).  This is the
  318.       size of the longest record  in  the  file,  and  consequently  the
  319.       minimum  size  of  the  storage  buffer  required to read the file
  320.       record by record.
  321.  
  322.   o   A "record format" (which is called recfm).   This "record  format"
  323.       is  a single character, F for FIXED or V for VARIABLE.  A recfm of
  324.       "F" indicates that all the records in the file  have  exactly  the
  325.       same  lrecl,  while "V" indicates the opposite.  The filing system
  326.       uses more efficient algorithms when handling recfm  F  files,  but
  327.       they require more disk space of course.
  328.  
  329.  
  330.  
  331.   Implementation considerations
  332.   -----------------------------
  333.  
  334.  
  335.   Before  you  start writing the conversion program, you must answer the
  336.   following set of questions:
  337.  
  338.   1.  Which name will I use on my system for the newly converted file?
  339.  
  340.       The sample C program reads from  standard  input  and  writes  the
  341.       converted  file  to  standard output, leaving the user responsible
  342.       for providing adequate redirection on the command line.
  343.       The sample PASCAL program, which is written for MS-DOS,  uses  the
  344.       filename  field as file name and the three first characters of the
  345.       filetype as file extension, i.e. filename+'.'+Left(filetype,3).
  346.       You may use a similar algorithm or select a constant  output  file
  347.       name such as "LISTSERV.PUN".
  348.  
  349.   2.  How should recfm F files be written on my system?
  350.  
  351.       The  sample  program treats a recfm F file as a recfm V file which
  352.       just happens to  have  records  of  identical  length.    A  CR+LF
  353.       sequence  is therefore output at the end of each record, regarless
  354.       of the recfm.  Alternatively, the program could have been designed
  355.       to write recfm F files "as is", i.e. without any CR+LF sequence at
  356.       the end of the record.  It all depends on the capabilities of your
  357.       system and (above all) of your system's editor.
  358.  
  359.  
  360.  
  361.  
  362.   SAMPLE PASCAL PROGRAM
  363.   _____________________
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.   *********************
  371.   * Preliminary notes *
  372.   *********************
  373.  
  374.  
  375.   This sample PASCAL program was written for Turbo-PASCAL  (a  trademark
  376.   of  Borland  International).    It is provided only as an example - no
  377.   warranty of any kind is made that the program will  function  properly
  378.   on  your  operating system.   Detailed comments have been provided for
  379.   all the "system dependent" procedures.  The program was  designed  for
  380.   transportability,  not  efficiency  -  there are a lot of places where
  381.   some optimization would greatly improve execution speed, but that  was
  382.   not  the  objective  of the program.  All the functions and procedures
  383.   which are not part of the  standard  library  have  been  Capitalized,
  384.   while standard functions have been entered in lower case.  These func-
  385.   tions might exist on some of the compilers, possibly under a different
  386.   name.  The compiler is assumed to be able to handle the "string" type;
  387.   if  it  doesn't,  you will have to write a few "string-handling" func-
  388.   tions which emulate strings from an array of char.
  389.  
  390.   Finally, since not all terminals accept the special characters used by
  391.   PASCAL, the following conversion has been made:
  392.  
  393.     opening bracket     --> (.
  394.     closing bracket     --> .)
  395.     opening curly brace --> (*
  396.     closing curly brace --> *)
  397.  
  398.  
  399.  
  400.   NOTE: in Turbo-PASCAL, string concatenation  is  done  using  the  "+"
  401.   sign.
  402.  
  403.  
  404.  
  405.  
  406.  
  407.   *----------------------------- Cut here --------------------------------*
  408.  
  409.      (*
  410.      * LISTSERV-Punch PASCAL conversion program, version number 03
  411.      *
  412.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  413.      *
  414.      *
  415.      * This public domain program has  been tested on an IBM PC-compatible
  416.      * system on several  small files that had to be  keyed-in manually on
  417.      * the PC since no PC-to-mainframe connection was available.
  418.      *
  419.      * The working version  of the program had to be  printed and re-keyed
  420.      * in manually into the document  you are reading. There can therefore
  421.      * be several  keying errors --  proofreading programs is  very tiring
  422.      * and consequently very difficult.
  423.      *
  424.      *
  425.      * Synopsis:
  426.      *
  427.      *   The input file from LISTSERV is assumed to be CARDS.DAT
  428.      *
  429.      *   Output is  directed to  file "filename.filetype", with filetype
  430.      *   being truncated to 3 characters of course.
  431.      *
  432.      *
  433.      * Problems:
  434.      *
  435.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  436.      *   Metaphysical complaints about the Rules of Structured Programming
  437.      *   and their relationship to  this blasphemous program should better
  438.      *   stay in their author's own warm, safe and cosy mailbox.
  439.      *
  440.      *)
  441.     program LPUNCH(input,cardfile,output,outfile);
  442.  
  443.     (* Note: Turbo-PASCAL requires square brackets for the "string" type,
  444.              while other compilers require parenthesis. Since some terminals
  445.              cannot display square brackets, parenthesis will be used. *)
  446.  
  447.     type cards=string(80);
  448.          string5=string(5); (* This is because Turbo is not a very power-  *)
  449.          string8=string(8); (* ful compiler                                *)
  450.          anystring=string(255); (* Substitute the maximum length of a
  451.                                    "string" var on your compiler *)
  452.  
  453.     var cardfile:text; (* Input file -- compiler dependent declaration *)
  454.         outfile:file of char;        (* compiler dependent declaration *)
  455.         card:cards;
  456.         filename,filetype:string8;
  457.         recfm:char;
  458.         i,ncards,lrecl,xlrecl:integer;
  459.  
  460.     function Substr(s:anystring;start,size:integer):anystring;
  461.     (* This function must return the substring of "s" starting at character
  462.        number "start" and of length "size". The resulting string must NOT be
  463.        padded with blanks if start+size-1 > length of the string. *)
  464.  
  465.       begin
  466.         Substr:=Copy(s,start,size)  (* Turbo has it under another name *)
  467.       end;
  468.  
  469.     function Length(s:anystring):integer;
  470.     (* This return the length of the string, with 0 for a null string *)
  471.  
  472.       begin
  473.         Length:=ord(s(.0.)) (* Same as the built-in Turbo function *)
  474.       end;
  475.  
  476.     procedure Opencards;
  477.     (* This procedure must open the input file, wherever it may be or your
  478.        system, and display an error message and exit it there is an error *)
  479.  
  480.       begin
  481.         assign(cardfile,'CARDS.DAT');
  482.         (*$i-*)
  483.         reset(cardfile);
  484.         (*$i+*)
  485.         if ioresult <> 0 then
  486.          begin
  487.            writeln('Error opening input file');
  488.            halt (* HALT is a GOTO just before the END. statement *)
  489.          end
  490.       end;
  491.  
  492.     procedure Closecards;
  493.     (* This procedure must close the input file. You may wish to have it
  494.        delete the input file too *)
  495.  
  496.       begin
  497.         (*$i-*)
  498.         close(cardfile);
  499.         if ioresult = 0 then; (* just reset turbo's hang... *)
  500.         (*$i+*)
  501.       end;
  502.  
  503.     function Getcard:cards;
  504.      var result:cards;
  505.     (* This function must read one 80-chars line (one "card") from input
  506.        and return it as result. A premature EOF is an error and must cause
  507.        termination of the program. The result must be EXACTLY 80 characters
  508.        in length *)
  509.  
  510.       begin
  511.         (*$i-*)
  512.         readln(cardfile,result);
  513.         (*$i+*)
  514.         if ioresult <> 0 then
  515.          begin
  516.            writeln('Premature EOF on input');
  517.            halt
  518.          end;
  519.         while Length(result) <> 80 do result:=result+' ';
  520.         Getcard:=result
  521.       end;
  522.  
  523.     function Dec2bin(s:string5):integer;
  524.      var n,error:integer;
  525.     (* This function converts a string of numeric characters into its
  526.        binary representation ("integer"). An error should cause termination*)
  527.  
  528.       begin
  529.         val(s,n,error);
  530.         if error = 0 then Dec2bin:=n
  531.                      else begin
  532.                             writeln('Invalid decimal argument');
  533.                             halt
  534.                           end
  535.       end;
  536.  
  537.     procedure Openout(fn,ft:string8);
  538.     (* This procedure must open the output file under whatever file-id you
  539.        may choose *)
  540.  
  541.       begin
  542.         assign(outfile,fn+'.'+Substr(ft,1,3));
  543.         (*$i-*)
  544.         rewrite(outfile);
  545.         (*$i+*)
  546.         if ioresult <> 0 then
  547.          begin
  548.            writeln('Error opening output file');
  549.            halt
  550.          end
  551.       end;
  552.  
  553.     procedure Closeout;
  554.     (* This procedure must close the output file. Errors should be detected
  555.        since they can mean a disk-full condition while writing the last
  556.        buffer, or suchlike *)
  557.  
  558.       begin
  559.         (*$i-*)
  560.         close(outfile);
  561.         if ioresult <> 0 then
  562.          begin
  563.            writeln('Error occured while closing output file');
  564.            halt
  565.          end
  566.         (*$i+*)
  567.       end;
  568.  
  569.     function Gobbleword(var card:cards):string5;
  570.      var s:string5;
  571.     (* This function should be left "as is" *)
  572.  
  573.       begin
  574.         s:='';
  575.         repeat
  576.           s:=s+card(.1.);
  577.           card:=Substr(card,2,80)
  578.         until card(.1.) = '/';
  579.         card:=Substr(card,2,80); (* Delete the "/" sign too *)
  580.         Gobbleword:=s
  581.       end;
  582.  
  583.     procedure Outchar(c:char);
  584.     (* This outputs a character to "outfile". On byte-based file systems such
  585.        as UNIX or MS-DOS, the character is just sent to standard output. On
  586.        record-based systems it must be appended to a buffer (string(65535) or
  587.        array of char) before the actual write is performed (see below) *)
  588.  
  589.       begin
  590.         (*$i-*)
  591.         write(outfile,c);
  592.         (*$i+*)
  593.         if ioresult <> 0 then
  594.          begin
  595.            writeln('Error writing to output file');
  596.            halt
  597.          end
  598.       end;
  599.  
  600.     procedure Endofrecord;
  601.     (* This procedure is called when the end of a record is reached. On
  602.        record-based file systems, the buffer must be written; on byte-based
  603.        systems a CR+LF (or similar) must be output for recfm V files, and
  604.        possibly for recfm F files (your option) *)
  605.  
  606.       begin
  607.         Outchar(chr(13));  (* CR *)
  608.         Outchar(chr(10))   (* LF *)
  609.       end;
  610.  
  611.     procedure Writeout(s:cards;var l:integer);
  612.      var i:integer;
  613.     (* This one must be left "as is" *)
  614.  
  615.       begin
  616.         if Length(s) > l then s:=Substr(s,1,l);
  617.         for i:=1 to Length(s) do Outchar(Substr(s,i,1));
  618.         l:=l-Length(s)
  619.       end;
  620.  
  621.     (* Main program -- nothing needs to be changed *)
  622.  
  623.     begin
  624.       Opencards;
  625.       repeat
  626.         card:=Getcard
  627.       until Substr(card,1,3) = 'ID/';
  628.  
  629.       filename:=Substr(card,4,8);
  630.       filetype:=Substr(card,13,8);
  631.       recfm:=Substr(card,22,1);
  632.       lrecl:=Dec2bin(Substr(card,24,5));
  633.  
  634.       Openout(filename,filetype);
  635.  
  636.       repeat
  637.         card:=Getcard;
  638.         if Substr(card,1,4) <> 'END/' then
  639.          begin
  640.            if recfm = 'V' then xlrecl:=Dec2bin(Gobbleword(card))
  641.                           else xlrecl:=lrecl;
  642.            ncards:=Dec2bin(Gobbleword(card));
  643.  
  644.            repeat
  645.              Writeout(card,xlrecl);
  646.              ncards:=ncards-1;
  647.              if ncards <> 0 then card:=Getcard
  648.            until ncards = 0;
  649.            for i:=1 to xlrecl do Outchar(' ');
  650.            Endofrecord
  651.          end
  652.       until Substr(card,1,4) = 'END/';
  653.  
  654.       Closecards;
  655.       Closeout;
  656.       writeln('File "',filename,' ',filetype,
  657.                    '" has been successfully converted.')
  658.     end.
  659.  
  660.     *----------------------------- Cut here --------------------------------*
  661.  
  662.  
  663.  
  664.  
  665.   SAMPLE C PROGRAM
  666.   ________________
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.   *********************
  674.   * Preliminary notes *
  675.   *********************
  676.  
  677.  
  678.   This  sample C program is provided only as an example - no warranty of
  679.   any kind is made that the program will function properly on your oper-
  680.   ating system.   Detailed comments  have  been  provided  for  all  the
  681.   "system dependent" procedures.  All the functions and procedures which
  682.   are  not  part  of  the  standard library have been Capitalized, while
  683.   standard functions have been entered in lower case.
  684.  
  685.   The program should operate properly as is on any standard UNIX system,
  686.   although some system-dependent additions might be  necessary  in  some
  687.   cases (e.g. special options on the output file fopen call, or addition
  688.   of command-line switches).
  689.  
  690.   Finally, since not all terminals accept the special characters used by
  691.   C, the following conversion has been made:
  692.  
  693.     opening bracket     --> (:
  694.     closing bracket     --> :)
  695.     opening curly brace --> (*
  696.     closing curly brace --> *)
  697.     backslash           --> <bs>
  698.  
  699.   You  should  be  able  to  reverse  this  conversion  easily with your
  700.   favourite text editor before compiling the program.
  701.  
  702.  
  703.  
  704.   *----------------------------- Cut here --------------------------------*
  705.  
  706.     /*
  707.      * LISTSERV-Punch C conversion program, version number 02
  708.      *
  709.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  710.      *
  711.      *
  712.      * This public domain program has been  tested on a VM system with the
  713.      * huge BITEARN NODES file as input (over 23,000 LISTSERV-Punch format
  714.      * records), as  well as several  other smaller files. No  problem has
  715.      * been encountered in the testing phase.
  716.      *
  717.      * The working version  of the program has  been electronically copied
  718.      * into the document  you are reading, untouched.  There can therefore
  719.      * be no keying error, or then it  was in the original program too and
  720.      * was not detected during the testing period.
  721.      *
  722.      *
  723.      * Synopsis:
  724.      *
  725.      *   The input file from LISTSERV is assumed to be the standard input.
  726.      *
  727.      *   Output is  directed to  the standard output,  but the  program is
  728.      *   structured in such a way that this can be easily changed.
  729.      *
  730.      *
  731.      * Problems:
  732.      *
  733.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  734.      *   Philosophical lectures about the  grandiose organization of C and
  735.      *   how  it has  been violated  in  this program  should be  directly
  736.      *   forwarded to /dev/null for a prompt answer.
  737.      *
  738.      */
  739.     #include <stdio.h>
  740.  
  741.     char card(:81:),     /* Input record image */
  742.          filename(:9:),
  743.          filetype(:9:),
  744.          number(:6:),    /* Scratch string to hold a number */
  745.          recfm;
  746.  
  747.     int  i,ncards,lrecl,xlrecl;
  748.  
  749.     FILE *outfile;
  750.  
  751.  
  752.     /* This function does not have to be tailored */
  753.     Substr(outstring,instring,start,length)
  754.      char *outstring,*instring;
  755.      int  start,length;
  756.     (*
  757.       register int rd=0,wr=0;
  758.       register char c;
  759.  
  760.      --start;
  761.      while(rd < start) (*
  762.        if (instring(:rd++:)=='<bs>0') (*
  763.          outstring="";
  764.          return;
  765.        *)
  766.      *)
  767.  
  768.      while(length-- > 0) (*
  769.        if ((c=instring(:rd++:)) != '<bs>0')
  770.         outstring(:wr++:)=c;
  771.        else break;
  772.      *)
  773.      outstring(:wr:)='<bs>0';
  774.      return;
  775.     *)
  776.  
  777.  
  778.     /* This function  must read one  80-chars line (one "card")  from input
  779.        and return it as result. A premature  EOF is an error and must cause
  780.        termination of the program. The result must be EXACTLY 80 characters
  781.        in length */
  782.     Getcard(string)
  783.     char *string;
  784.     (*
  785.       register int i=0,c;
  786.  
  787.       while(i < 80) (*
  788.         if (((c=getchar()) != EOF) && (c != '<bs>n'))
  789.           string(:i++:)=c;
  790.         else
  791.           break;
  792.       *)
  793.       if (c == EOF) (*
  794.         fprintf(stderr,"Premature EOF on input.<bs>n");
  795.         exit(100); *)
  796.  
  797.       if (i==80) (*
  798.         if (getchar() != '<bs>n') (*
  799.           fprintf(stderr,"Input file contains records larger than 80.<bs>n");
  800.           exit(100);
  801.         *)
  802.       *)
  803.       while (i < 80) (*
  804.         string(:i++:)=' ';
  805.       *)
  806.       string(:i:)='<bs>0';
  807.       return;
  808.     *)
  809.  
  810.  
  811.     /* This function does not have to be tailored */
  812.     Dec2bin(result,string)
  813.     char *string;
  814.     int  *result;
  815.     (*
  816.       if (sscanf(string,"%d",result) != 0) return;
  817.       fprintf(stderr,"Invalid decimal argument -- '%s'.<bs>n",string);
  818.       exit(100);
  819.     *)
  820.  
  821.  
  822.     /* This procedure must open the output file under whatever file-id you
  823.        may choose */
  824.     Openout(fn,ft)
  825.     char *fn,*ft;
  826.     (*
  827.       /* Our implementation uses standard output as file pointer */
  828.       outfile=stdout;
  829.  
  830.       /* The following instruction must be uncommented for use under
  831.          most VM C's if the output file is to have a lrecl > 80 */
  832.       /* outfile=fopen("LPUNCH OUTPUT A (recfm v lrecl 65535","w"); */
  833.       return;
  834.     *)
  835.  
  836.  
  837.     /* This procedure must close the output file. Errors should be detected
  838.        since they  can mean  a disk-full condition  while writing  the last
  839.        buffer, or suchlike */
  840.     Closeout()
  841.     (* /* The chosen implementation does nothing and relies on the operating
  842.          system  to  close the  standard  output  file.  This is  not  good
  843.          programming practice but at least it's transportable. */
  844.       return;
  845.     *)
  846.  
  847.  
  848.     /* This function should be left "as is" */
  849.     Gobbleword(inpstring,outstring)
  850.     char *inpstring,*outstring;
  851.     (*
  852.       register int rd=0,wr=0;
  853.  
  854.       while (inpstring(:rd:) != '/') (*
  855.         outstring(:wr++:)=inpstring(:rd++:);
  856.       *)
  857.       outstring(:wr:)='<bs>0';
  858.  
  859.       for(wr=0;inpstring(:++rd:) != '<bs>0';) (*
  860.         inpstring(:wr++:)=inpstring(:rd:);
  861.       *)
  862.       inpstring(:wr:)='<bs>0';
  863.       return;
  864.     *)
  865.  
  866.  
  867.     /* This function does not have to be tailored */
  868.     Writeout(string,lenptr)
  869.     char *string;
  870.     int  *lenptr;
  871.     (*
  872.       int i=0;
  873.       while((string(:i:) != '<bs>0') && ( *lenptr > 0)) (*
  874.         putc(string(:i++:),outfile);
  875.         --( *lenptr);
  876.       *)
  877.     *)
  878.  
  879.  
  880.     /* Main program -- nothing needs to be changed */
  881.     main() (*
  882.  
  883.       do (* /* Read up to and including 'ID/' card */
  884.         Getcard(card);
  885.     *) while ((card(:0:)!='I') || (card(:1:)!='D') || (card(:2:)!='/'));
  886.  
  887.       Substr(filename,card,4,8);
  888.       Substr(filetype,card,13,8);
  889.       recfm=card(:21:);
  890.       Substr(number,card,24,5);
  891.       Dec2bin(&lrecl,number);
  892.  
  893.       Openout(filename,filetype);
  894.  
  895.       for (;;) (*
  896.         Getcard(card);
  897.         if ((card(:0:)=='E') && (card(:1:)=='N') &&
  898.             (card(:2:)=='D') && (card(:3:)=='/'))
  899.           break;
  900.  
  901.         if (recfm=='V') (*
  902.           Gobbleword(card,number);
  903.           Dec2bin(&xlrecl,number); *)
  904.         else
  905.           xlrecl=lrecl;
  906.  
  907.         Gobbleword(card,number);
  908.         Dec2bin(&ncards,number);
  909.  
  910.         do (*
  911.           Writeout(card,&xlrecl);
  912.           if (--ncards != 0)
  913.             Getcard(card);
  914.       *) while(ncards!=0);
  915.  
  916.         for(i=1;i <= xlrecl;i++) (*
  917.           putc(' ',outfile);
  918.         *)
  919.         putc('<bs>n',outfile);
  920.       *)
  921.       Closeout();
  922.     *)
  923.  
  924.     *----------------------------- Cut here --------------------------------*
  925.  
  926.  
  927.  
  928.  
  929.  
  930.   *************************************
  931.   * Appendix A.  The LISTSERV Library *
  932.   *************************************
  933.  
  934.       o User's guide  . . . . . . . . . . . . . . . . . . . .  (U01-001)
  935.  
  936.       o List Manager's guide  . . . . . . . . . . . . . . . .  (M01-002)
  937.  
  938.       o Installation guide  . . . . . . . . . . . . . . . . .  (S01-003)
  939.  
  940.       o Application Programmer's guide  . . . . . . . . . . .  (A01-004)
  941.  
  942.       o Maintenance guide . . . . . . . . . . . . . . . . . .  (S01-005)
  943.  
  944.       o File Server Functions . . . . . . . . . . . . . . . .  (U01-006)
  945.  
  946.   --> o Listserv-Punch Implementation . . . . . . . . . . . .  (R01-007)
  947.  
  948.       o File Maintainer's guide . . . . . . . . . . . . . . .  (M01-008)
  949.  
  950.       o BITNET-Oriented Presentation  . . . . . . . . . . . .  (P01-009)
  951.  
  952.       o Public Utilities Reference  . . . . . . . . . . . . .  (A01-010)
  953.  
  954.       o Licensed Utilities Reference  . . . . . . . . . . . .  (S01-011)
  955.  
  956.       o Database Functions  . . . . . . . . . . . . . . . . .  (U01-012)
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.   LISTSERV Document Numbers
  967.   -------------------------
  968.  
  969.                                 U 01 - 006 - 0
  970.                                 _ __   ___   _
  971.                                 |  |    |    |
  972.   Document Class     -----------+  |    |    |
  973.                                    |    |    |
  974.                                    |    |    |
  975.                                    |    |    |
  976.   Product Number     --------------+    |    |
  977.                                         |    |
  978.                                         |    |
  979.                                         |    |
  980.   Publication Number -------------------+    |
  981.                                              |
  982.                                              |
  983.                                              |
  984.   Revision Number    ------------------------+
  985.  
  986.  
  987.  
  988.   Document Class
  989.  
  990.  
  991.   The Document Class indicates for which category of persons the  publi-
  992.   cation was written.  The current classes are:
  993.  
  994.   A    Documents  intended  for Application Programmers.  These publica-
  995.        tions are usually very technical.
  996.  
  997.   M    Documents intended for Software Managers, i.e.  operators,  "list
  998.        owners", "file maintainers", et al.
  999.  
  1000.   P    General  Presentation  documents  intended for persons who do not
  1001.        have any particular knowledge in the product.   These are  gener-
  1002.        ally non-technical documents.
  1003.  
  1004.   R    Reference  documents  defining  protocols  used  by  the product.
  1005.        These documents are very technical and are  intended  for  people
  1006.        who  have  to write interfaces for the product or attempt to port
  1007.        it to an operating system or environment for  which  it  was  not
  1008.        originally written.
  1009.  
  1010.   S    Documents  intended  for  Systems Programmers, i.e.   the persons
  1011.        responsible for the installation and operation of the product.
  1012.  
  1013.   U    Documents intended for General Users.
  1014.  
  1015.  
  1016.  
  1017.  
  1018.   Product Number
  1019.  
  1020.  
  1021.   The Product Number is a unique number associated with the  product  to
  1022.   which  the  publication relates.  Number 01 refers to LISTSERV, number
  1023.   02 corresponds to the NETINFO sub-product, etc.
  1024.  
  1025.  
  1026.  
  1027.   Publication Number
  1028.  
  1029.  
  1030.   This is a unique number associated with the publication.   Publication
  1031.   Numbers  are  assigned  sequentially, disregarding the Document Class.
  1032.   There is a different set of Publication Numbers for each product.
  1033.  
  1034.  
  1035.  
  1036.   Revision Number
  1037.  
  1038.  
  1039.   This number is incremented at every release change in the publication.
  1040.   Fractional numbers indicate intermediate changes between two releases.
  1041.  
  1042.  
  1043.  
  1044.